package cloud.tianai.mate.captcha.generator.impl;

import cloud.tianai.captcha.common.constant.CommonConstant;
import cloud.tianai.captcha.generator.ImageTransform;
import cloud.tianai.captcha.generator.common.model.dto.*;
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
import cloud.tianai.captcha.resource.common.model.dto.Resource;
import cloud.tianai.mate.captcha.generator.common.util.MateCaptchaImageUtils;
import lombok.Getter;
import lombok.Setter;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

import static cloud.tianai.mate.captcha.common.constant.MateCaptchaTypeConstant.IMAGE_CLICK;

/**
 * @Author: 天爱有情
 * @date 2022/4/27 11:46
 * @Description 点选验证码
 */
public class MateIconClickImageCaptchaGenerator extends AbstractClickImageCaptchaGenerator {

    @Getter
    @Setter
    protected Integer clickImgWidth = 100;
    @Getter
    @Setter
    protected Integer clickImgHeight = 100;
    @Getter
    @Setter
    protected int tipImageInterferenceLineNum = 5;
    @Getter
    @Setter
    protected int tipImageInterferencePointNum = 50;
    /** 参与校验的数量. */
    @Getter
    @Setter
    protected Integer checkClickCount = 4;
    /** 干扰数量. */
    @Getter
    @Setter
    protected Integer interferenceCount = 2;

    public MateIconClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) {
        super(imageCaptchaResourceManager);
    }

    public MateIconClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, ImageTransform imageTransform, CaptchaInterceptor interceptor) {
        super(imageCaptchaResourceManager);
        setImageTransform(imageTransform);
        setInterceptor(interceptor);
    }

    @Override
    protected List<Resource> randomGetClickImgTips(GenerateParam param) {
        int tipSize = interferenceCount + checkClickCount;
        Set<Resource> tipSet = new HashSet<>(tipSize);
        while (tipSet.size() != tipSize) {
            Resource resource = getImageResourceManager().randomGetResource(CommonConstant.IMAGE_CLICK_ICON, param.getTemplateImageTag());
            tipSet.add(resource);
        }
        return new ArrayList<>(tipSet);
    }

    @Override
    protected void doInit() {
//        ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
//        // 添加一些系统的资源文件
//        resourceStore.addResource(IMAGE_CLICK, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG));
//
//        // 添加icon
//        resourceStore.addResource(CommonConstant.IMAGE_CLICK_ICON, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/icon/1.png"), DEFAULT_TAG));
//        resourceStore.addResource(CommonConstant.IMAGE_CLICK_ICON, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/icon/2.png"), DEFAULT_TAG));
//        resourceStore.addResource(CommonConstant.IMAGE_CLICK_ICON, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/icon/3.png"), DEFAULT_TAG));
//        resourceStore.addResource(CommonConstant.IMAGE_CLICK_ICON, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/icon/4.png"), DEFAULT_TAG));
//        resourceStore.addResource(CommonConstant.IMAGE_CLICK_ICON, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/icon/5.png"), DEFAULT_TAG));
//        resourceStore.addResource(CommonConstant.IMAGE_CLICK_ICON, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/icon/6.png"), DEFAULT_TAG));
//        resourceStore.addResource(CommonConstant.IMAGE_CLICK_ICON, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/icon/7.png"), DEFAULT_TAG));
//        resourceStore.addResource(CommonConstant.IMAGE_CLICK_ICON, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/icon/8.png"), DEFAULT_TAG));

    }

    public ImgWrapper genTipImage(List<ClickImageCheckDefinition> imageCheckDefinitions) {
        BufferedImage tipImage = new BufferedImage(clickImgWidth * imageCheckDefinitions.size(), clickImgHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = tipImage.createGraphics();
        String tips = imageCheckDefinitions.stream().map(c -> c.getTip().getData()).collect(Collectors.joining());

        for (int i = 0; i < imageCheckDefinitions.size(); i++) {
            ClickImageCheckDefinition imageCheckDefinition = imageCheckDefinitions.get(i);
            Resource tip = imageCheckDefinition.getTip();
            InputStream stream = getImageResourceManager().getResourceInputStream(tip);
            BufferedImage bufferedImage = CaptchaImageUtils.wrapFile2BufferedImage(stream);
            try {
                stream.close();
            } catch (IOException e) {
                // ignore
            }
            if (bufferedImage.getWidth() != clickImgWidth || bufferedImage.getHeight() != clickImgHeight) {
                // 重新缩放一下
                bufferedImage = MateCaptchaImageUtils.toBufferedImage(bufferedImage.getScaledInstance(clickImgWidth, clickImgHeight, Image.SCALE_SMOOTH));
            }
            graphics.drawImage(bufferedImage, i * clickImgWidth, 0, clickImgWidth, clickImgHeight, null);
        }
        // 加点干扰线
        MateCaptchaImageUtils.drawInterfere(graphics, tipImage.getWidth(), tipImage.getHeight(), tipImageInterferenceLineNum, tipImageInterferencePointNum);
        graphics.dispose();
//        tipImage = CaptchaImageUtils.gray(tipImage);
        return new ImgWrapper(tipImage, new Resource(null, tips), null);
    }

    @Override
    public ImgWrapper getClickImg(Resource tip, Color randomColor) {
        // 随机角度
        int randomDeg = randomInt(0, 85);
        BufferedImage bufferedImage = getResourceImage(tip);
        bufferedImage = CaptchaImageUtils.rotateImage(bufferedImage, randomDeg);
        if (bufferedImage.getWidth() != clickImgWidth || bufferedImage.getHeight() != clickImgHeight) {
            // 重新缩放一下
            bufferedImage = MateCaptchaImageUtils.toBufferedImage(bufferedImage.getScaledInstance(clickImgWidth, clickImgHeight, Image.SCALE_SMOOTH));
        }
        return new ImgWrapper(bufferedImage, tip, null);
    }

    @Override
    protected List<ClickImageCheckDefinition> filterAndSortClickImageCheckDefinition(List<ClickImageCheckDefinition> allCheckDefinitionList) {
        // 打乱
        Collections.shuffle(allCheckDefinitionList);
        // 拿出参与校验的数据
        List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList = new ArrayList<>(checkClickCount);
        for (int i = 0; i < checkClickCount; i++) {
            ClickImageCheckDefinition clickImageCheckDefinition = allCheckDefinitionList.get(i);
            checkClickImageCheckDefinitionList.add(clickImageCheckDefinition);
        }
        return checkClickImageCheckDefinitionList;
    }

    @Override
    public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) {

        List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList = (List<ClickImageCheckDefinition>) captchaExchange.getTransferData();
        GenerateParam param = captchaExchange.getParam();
        BufferedImage bgImage = captchaExchange.getBackgroundImage();
        Resource resourceImage = captchaExchange.getResourceImage();
        CustomData customData = captchaExchange.getCustomData();
        // 提示图片
        BufferedImage tipImage = genTipImage(checkClickImageCheckDefinitionList).getImage();
        ImageTransformData transform = getImageTransform().transform(param, bgImage, tipImage, resourceImage, checkClickImageCheckDefinitionList, customData);
        ImageCaptchaInfo clickImageCaptchaInfo = new ImageCaptchaInfo();
        clickImageCaptchaInfo.setBackgroundImage(transform.getBackgroundImageUrl());
        clickImageCaptchaInfo.setBackgroundImageTag(resourceImage.getTag());
        clickImageCaptchaInfo.setTemplateImage(transform.getTemplateImageUrl());
        clickImageCaptchaInfo.setBackgroundImageWidth(bgImage.getWidth());
        clickImageCaptchaInfo.setBackgroundImageHeight(bgImage.getHeight());
        clickImageCaptchaInfo.setTemplateImageWidth(tipImage.getWidth());
        clickImageCaptchaInfo.setTemplateImageHeight(tipImage.getHeight());
        clickImageCaptchaInfo.setRandomX(null);
        clickImageCaptchaInfo.setTolerant(null);
        clickImageCaptchaInfo.setType(IMAGE_CLICK);
        customData.setExpand(checkClickImageCheckDefinitionList);
        return clickImageCaptchaInfo;
    }

}
